通信制御用APIを使ったシリアル通信プログラム開発



<項目>API関数
API(Application Programming Interface)関数は、Windows自体が持っている機能です。Windows上で動作するアプリケーションであれば、共通して使うことができます。DLL(Dinamic Link Library)ファイルで提供されています。API関数の数は、数百種あって、Windowsの主たる機能が納められています。Visual Basicは、たくさんの命令を持ってはいますが、すべてのWindows機能を網羅しているわけではなく、Visual Basicの命令で実行できないものは、直接API関数を呼び出して利用することになります。初めてAPI関数を活用する読者にとっては、何やら難しいというイメージを持つかもしれませんが、便利なプロシージャの一つと思ってください。「Declare」宣言文で定義するだけで、他のプロシージャと同じように利用することができます。API関数に慣れてしまえば、Visual BasicでほとんどのWindowsプログラミングが可能になります。シリアル通信ですが、CreateFile(API関数)でポートをオープンし、WriteFile/ReadeFile(API関数)でデータを送受し、CloseHandle(API関数)でクローズするというようにAPI関数を使っていきます。


<項目>APIビューアの利用の仕方
Visual Basicには、APIビューアというDeclare文や構造体の内容、定数の値を簡単に取り込めるソフトがありますので、まずはその使い方をマスターしましょう。ここでは、シリアルポート関連のAPI関数として、「CreateFile関数」の例を用いて説明します。手順は次の通りです。

APIビューアの使い方
図1.APIビューアの使い方
  1. まずは、APIビューアを起動します。ファイル()から、テキストファイルの読み込み()...をクリックすると、API関数の宣言文をテキスト化して集めた「Win32Api.TXT」のファイルがありますので、このテキストAPIファイルを開いてください。
  2. ファイルを読み込んだら、種類()を、関数にします。
  3. 有効な項目():の欄からたとえば、「CreateFile」という関数にフォーカスを移動し、追加()をクリックします。フォーカスを移動する際には、必要とするAPI関数の頭文字を入力していくと、その文字で始まる関数にジャンプしていきます。
  4. 選択された項目()...に、Declare文の内容が表示されるので、コピー()をクリックすれば、クリップボードに保存されます。

Visual Basicの標準モジュールを追加して、その宣言領域にDeclare文をペーストすれば、Visual BasicでAPI関数が利用できるようになります。

また、構造体については、

  1. APIビューアを起動し、同様にして「Win32Api.TXT」のテキストAPIファイルを開く。
  2. ファイルを読み込んだら、種類()を、型にします。
  3. 有効な項目():の欄からたとえば、「DCB」という型にフォーカスを移動し、追加()をクリックします。フォーカスを移動する際には、必要とする型の頭文字を入力していくと、その文字で始まる型にジャンプしていきます。
  4. 選択された項目()...に、Type文の内容が表示されるので、コピー()をクリックすれば、クリップボードに保存されます。


なお、API関数の宣言文をテキスト化して集めた「Win32Api.TXT」のファイルは、
Program Files \ DevStudio \ Vb \ Winapi のディレクトリの下に置かれています。


<項目>API関数の利用の仕方
API関数やDLLに含まれるプロシージャを利用するためには、Declare宣言文として記述することで利用できます。宣言文には、DLLに含まれているプロシージャ名(API関数名)と、引数のタイプを記述します。記述場所は、標準モジュール宣言領域(GeneralのDeclarations)か、フォームモジュール宣言領域になります。標準モジュールに記述した場合には、どのモジュールからでも利用することができますが、フォームモジュールに記述した場合には、そのモジュール内だけしか有効になりませんので、「Private」をDeclareの前につける必要があります。したがって、APIビューアでそのままコピーして張り付けるような場合には、標準モジュール内で宣言しておく方が簡単です。なお、標準モジュール内で宣言するといっても、宣言領域を使うだけであり、プログラムを標準モジュールからスタートさせる必要はありません。
宣言文のタイプは、「Function」タイプと、「Sub」タイプの2種類がありますが、API関数のほとんどは「Function」タイプを使います。タイプの違いですが、「Function」は戻り値があるのに対して、「Sub」は戻り値がありません。
宣言文の内容は、プロシージャ名、DLLファイル名、引数のタイプです。プロシージャ名は、「Alias」を使ってDLL内での名称とは別にすることがあります。これは、Visual Basicでは許されない記述方法として、_で始まるプロシージャがあった場合に、Visual Basicで呼び出し可能なプロシージャ名に変更しています。API関数においては、「ByVal」で引数を渡すことが多いです。「ByVal」指定をすると値渡しとなります。

●API関数(DLL内プロシージャ)のDeclare宣言文の一般形式

Declare Function プロシージャ名(API関数) Lib "DLLファイル名" [Alias"DLL内でのプロシージャ名"]
  引数1引数2,・・・) As Type

●実行文の一般形式

dummy = プロシージャ名(API関数) (引数1引数2,・・・)

それでは、次にシリアル通信に関連する主なAPI関数を解説していきましょう。


<項目>シリアルポートのオープン(CreateFile関数)について
シリアルポートを利用するときには、ファイルと同じ手続きをします。ファイルをオープンするようにポートをオープンします。API関数は、CreateFile関数になります。
Win32Api.TXTの内容(CreateFile関数)は、以下のようになっています。

Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long


CreateFile関数の実行文

  戻り値=CreateFile ( [1] ファイル名, [2] オープン方法, [3] 共有モード,  [4] セキュリティ属性, [5] 既存ファイルの処理, [6] ファイルの属性, [7] テンプレートファイル )

戻り値は、成功すればハンドル値、失敗すれば「−1」を返します。
なお、CreateFile関数の引数についての設定は、表1を参照してください。

表1.CreateFile関数の引数とシリアルポートの場合の設定について
  引数(パラメータ) 型(変数定義) 意味 設定のポイント
[1] lpFileName String ファイル名 "COM1","COM2"など
本リストでは"COM1"を指定
[2] dwDesiredAccess Long オープン方法 読み書き両用にする
「&H80000000 OR &H40000000」
[3] dwShareMode Long 共有モード 共有しない「0」
[4] lpSecurityAttributes SECURITY_ATTRIBUTES
→Longに変更する
セキュリティ属性 使用しない
宣言文の型を変更して「0」
[5] dwCreationDisposition Long 既存ファイルの処理 既存のファイルをオープン
「&H3」を指定する
[6] dwFlagsAndAttributes Long ファイルの属性 なし「0」
[7] hTemplateFile Long テンプレートファイル 使わない「0」

<ここがポイント>CreateFile関数は、そのままでは構造体を含む形になっているので、4番目のパラメータの変数定義「SECURITY_ATTRIBUTES」を「Long」に変更します。また、引数の先頭に「ByVal」も付けておいてください。これで、この部分の設定は「0」を与えるだけでよくなります。


<項目>シリアルポートのクローズ(CloseHandle関数)について
シリアルポートに関する操作を行った後には、ポートをクローズします。API関数は、CloseHandle関数になります。
Win32Api.TXTの内容(CloseHandle関数)は、以下のようになっています。引数は、クローズするハンドルを渡すだけです。

Declare Function CloseHandle Lib "kernel32" Alias "CloseHandle" (ByVal hObject As Long) As Long

CloseHandle関数の実行文

  戻り値 = CloseHandle ( ポートのハンドル )

戻り値は、成功すれば「0」、失敗すればハンドルをそのまま返す。

●プログラム開発上での注意点
ポートをオープンした後に、何らかの理由でエラーになったりすると、ポートはオープンのままになってしまいます。オープンのままですと、次に開こうとしてもオープンできません。一番簡単な対処法は、ポートが開けなくなったら、いったんVisual Basicを終了するとクローズします。開発中はよく起きるトラブルですので、オープン後にハンドル番号をフォームなどに表示させてその番号を確認し、その番号をもとにオープン前にクローズしておくようにすると回避できます。ハンドル値は、Visual Basic起動後は一定の値になりますが、起動するたびに変化しますので注意してください。


<項目>シリアルポートの設定(SetCommState関数)について
ポートをオープンした後、伝送方法を設定します。API関数は、SetCommState関数になります。パラメータとしてハンドルとDCB構造体が必要になります。DCB構造体では、必要な伝送方法のほとんどを設定することができます。Win32Api.TXTの内容(SetCommState関数)は、以下のようになっています。

Declare Function SetCommState Lib "kernel32" Alias "SetCommState" (ByVal hCommDev As Long, lpDCB As DCB) As Long

SetCommState関数の実行文

  戻り値 = SetCommState ( ポートのハンドル, DCB構造体 )

なお、DCB構造体のメンバについては、表2を参照してください。


<項目>シリアルポートの状態取得(GetCommState関数)について
ポートの状態を取得するAPI関数は、GetCommState関数になります。パラメータとしてハンドルとDCB構造体が必要になります。Win32Api.TXTの内容(GetCommState関数)は、以下のようになっています。

Declare Function GetCommState Lib "kernel32" Alias "GetCommState" (ByVal nCid As Long, lpDCB As DCB) As Long

GetCommState関数の実行文

  戻り値 = GetCommState ( ポートのハンドル, DCB構造体 )

なお、DCB構造体のメンバについては、表2を参照してください。

表2.DCB構造体のメンバ
メンバ   型   意味
DCBlength Long 構造体のサイズ
BaudRate Long ボーレート(bps)の設定・・・直接値を代入する。
例:110, 150, 300, 600, 1200, 2400, 4800,
   9600, 14400, 19200, 38400
fBitFields Long 表3を参照
wReserved Integer 予約(0をセットする)
XonLim Integer 受信バッファ中のデータが何バイトになったら
Xon文字を送るかを指定
XoffLim Integer 受信バッファの空きが何バイトになったら
Xoff文字を送るかを指定
ByteSize Byte 1データのビット数を指定・・・7または8
Parity Byte パリティの方式を指定
0・・・NOPARITY   (パリティなし)
1・・・ODDPARITY  (奇数パリティ)
2・・・EVENPARITY  (偶数パリティ)
3・・・MARKPARITY  (常にマーク)
StopBits Byte ストップビット数を指定
0・・・ONESTOPBIT   (1ビット)
1・・・ONE5STOPBITS (1.5ビット)
2・・・TOSTOPBITS   (2ビット)
XonChar Byte Xon文字を指定
XoffChar Byte xoff文字を指定
ErrorChar Byte パリティエラーの場合に使う文字を指定
EofChar Byte 非バイナリモードの場合のデータ終了文字の指定
EvtChar Byte イベントを生成する文字を指定
wReserved1 Integer (未使用)


表3.fBitFieldsのフィールド内容
(実際はビット単位の処理なので、まとめてfBitFieldsとして定義されている)
ビット フィールド名 意味
fBinary バイナリモードかどうか
fParity パリティチェックの有無
fOutxCtsFlow CTSを監視するかどうか
fOutxDsrFlow DSRを監視するかどうか
5,6 fDtrControl DTRによるハンドシェーク(2ビット)
fDsrSensitivity TrueのときDSRがオフのときの受信データを無視する
fTXContinueOnXoff Xoff文字を送信した後も送信を続けるかどうか
fOutX TrueのときXoff文字を受信すると送信を停止し、
Xon文字で再開
10 fInX Trueのとき受信バッファの空きに応じて
Xoff、Xon文字が送信される
11 fErrorChar Trueのときパリティエラーの処理をする
12 fNull Trueのときヌル文字は破棄される
13,14 fRtsControl RTSによるハンドシェーク(2ビット)
15 fAbortOnError Trueのときエラーが発生したら読み書きを終了する
16 fDummy2 未使用

(注意)Visual Basic バージョン4.0のAPIビューアで取得したDCBの内容についてはバグがあります。ビット単位でまとめてfBitFieldsとして定義されるべきところを、フィールド(表3)を個々にLong型で定義されてしまっています。


<項目>タイムアウトの設定(SetCommTimeouts関数)について
外付け装置に異常があるため、データが受け取れずハングアップのような状態に陥ってしまうことがよくあります。このようなことを回避するために、タイムアウトの時間を設定します。API関数は、SetCommTimeouts関数になります。パラメータとしてハンドルとCOMMTIMEOUTS構造体が必要になります。Win32Api.TXTの内容(SetCommTimeouts関数)は、以下のようになっています。

Declare Function SetCommTimeouts Lib "kernel32" Alias "SetCommTimeouts" (ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS) As Long


SetCommTimeouts関数の実行文

  戻り値 = SetCommTimeouts ( ポートのハンドル, COMMTIMEOUTS構造体 )

なお、COMMTIMEOUTS構造体のメンバについては、表4を参照してください。


<項目>タイムアウトの状態取得(GetCommTimeouts関数)について
API関数は、GetCommTimeouts関数になります。タイムアウトの設定の状態を確認することができます。パラメータとしてハンドルとCOMMTIMEOUTS構造体が必要になります。Win32Api.TXTの内容(GetCommTimeouts関数)は、以下のようになっています。

Declare Function GetCommTimeouts Lib "kernel32" Alias "GetCommTimeouts" (ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS) As Long

GetCommTimeouts関数の実行文

  戻り値 = GetCommTimeouts ( ポートのハンドル, COMMTIMEOUTS構造体 )

なお、COMMTIMEOUTS構造体のメンバについては、表4を参照してください。

表4.COMMTIMEOUTS構造体のメンバ
メンバ   型   意味
ReadIntervalTimeout Long 文字の読み込みの待ち時間
ReadTotalTimeoutMultiplier Long 読み込みの1文字あたりの時間
ReadTotalTimeoutConstant Long 読み込みの定数時間
WriteTotalTimeoutMultiplier Long 書き込みの1文字あたりの時間
WriteTotalTimeoutConstant Long 書き込みの定数時間

1番目(ReadIntervalTimeout)が、読み込みの待ち時間です。また、2番目以降のメンバを使って、トータルの時間も設定できます。たとえば、100文字読み込む場合には、1文字あたりの時間(2番目)×100+定数時間(3番目)がトータル時間となり、これを越えると処理が中止されます。


<項目>データの送信(WriteFile関数)について
データを送信するAPI関数は、WriteFile関数になります。Win32Api.TXTの内容(WriteFile関数)は、以下のようになっています。

Declare Function WriteFile Lib "kernel32" Alias "WriteFile" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As OVERLAPPED) As Long


WriteFile関数の実行文

  戻り値 = WriteFile ( ポートのハンドル, 送信データ, 送信したい数, 送信した数, 0 )

戻り値は、成功すれば「1」、失敗すれば「0」

2番目のパラメータは、送信するデータであり、「Any」なので文字列でも、数値でも可能です。ただし、文字列もしくはバイト配列の場合には固定長にしておく必要があります。また文字変数を使う場合には、文字変数は変数名を指定しても実際に文字が格納されているポインタを引き渡すことができませんので、必ず「ByVal」をつけてください。怠ると保護違反になります。宣言文には、「ByVal」がついていないので実行文の方につけておきます。3番目のパラメータでは、送信したいバイト数を厳密に指定してください。4番目のパラメータは、実際にやりとりしたバイト数が格納されます。宣言文の中には、5番目のパラメータにOVERLAPPED構造体が入っていますが、今回の用途では使用しないので、Long型に変更しておきます。実行文では ByVal 0& を与えます(単なる0でもよい)。


<項目>データの受信(ReadFile関数)について
データを受信するAPI関数は、ReadFile関数になります。Win32Api.TXTの内容(ReadFile関数)は、以下のようになっています。

Declare Function ReadFile Lib "kernel32" Alias "ReadFile" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As OVERLAPPED) As Long


ReadFile関数の実行文

  戻り値 = ReadFile ( ポートのハンドル, 受信データ, 受信したい数, 受信した数, 0 )

戻り値は、成功すれば「1」、失敗すれば「0」

2番目のパラメータは、受信するデータであり、「Any」なので文字列でも、数値でも可能です。ただし、文字列もしくはバイト配列の場合には固定長にしておく必要があります。また文字変数を使う場合には、文字変数は変数名を指定しても実際に文字が格納されているポインタを引き渡すことができませんので、必ず「ByVal」をつけてください。怠ると保護違反になります。宣言文には、「ByVal」がついていないので実行文の方につけておきます。3番目のパラメータでは、受信したいバイト数を「100バイト」などのように大きめに指定しておきます。4番目のパラメータで、実際にやりとりしたバイト数がわかりますので、後から必要な文だけ取り出します。宣言文の中には、5番目のパラメータにOVERLAPPED構造体が入っていますが、今回の用途では使用しないので、Long型に変更しておきます。実行文では ByVal 0& を与えます(単なる0でもよい)。


<項目>シリアルポートの機能調査(GetCommProperties関数)について
ポートの機能を調べるAPI関数は、GetCommProperties関数になります。パラメータとしてハンドルとCOMMPROP構造体が必要になります。Win32Api.TXTの内容(GetCommProperties関数)は、以下のようになっています

Declare Function GetCommProperties Lib "kernel32" Alias "GetCommProperties" (ByVal hFile As Long, lpCommProp As COMMPROP) As Long

GetCommProperties関数の実行文

  戻り値 = GetCommProperties ( ポートのハンドル, COMMPROP構造体 )

なお、COMMPROP構造体のメンバについては、表5を参照してください。

表5.COMMPROP構造体のメンバ
メンバ   型   意味
wPacketLength Integer 構造体のサイズ
wPacketVersion Integer 構造体のバージョン
dwServiceMask Long 実装されているサービス
dwReserved1 Long 予約
dwMaxTxQueue Long 最大送信バッファサイズ
dwMaxRxQueue Long 最大受信バッファサイズ
dwMaxBaud Long 最大ボーレート
dwProvSubType Long デバイスの種類
dwProvCapabilities Long サポートされている機能
dwSettableParams Long 変更可能なパラメータ
dwSettableBaud Long 許されるボーレート
wSettableData Integer 許されるバイトサイズ
wSettableStopParity Integer 許されるストップビット/パリティの設定
dwCurrentTxQueue Long 送信バッファサイズ
dwCurrentRxQueue Long 受信バッファサイズ
dwProvSpec1 Long プロバイダ用
dwProvSpec2 Long
wcProvChar(1) Integer


サポートされている機能は、COMMPROPの「dwProvCapabilities」メンバと、表6のフラグを用いて知ることができます。
たとえば、DTR/DSRの機能は、メンバの1ビット目に記されていますので、&H1&と論理和をとれば知ることができます。ほとんどのパソコンは、16ビットの特殊なデータモード以外はすべてサポートしていると思います。

表6.サポートされている機能を調べるフラグ値
定数   値   サポートされている機能
PCF_DTRDSR &H1& DTR/DSR機能
PCF_RTSCTS &H2& RTS/CTS機能
PCF_RLSD &H4& CD機能
PCF_PARITY_CHECK &H8& パリティチェック
PCF_XONXOFF &H10& XON/XOFFのフロー制御
PCF_SETXCHAR &H20& XON/XOFF機能の設定
PCF_TOTALTIMEOUTS &H40& 経過時間のタイムアウト
PCF_INTTIMEOUTS &H80& インターバルタイムアウト
PCF_SPECIALCHARS &H100& 特殊文字
PCF_16BITMODE &H200& 16ビットのデータモード



<項目>シリアルポート制御信号の直接操作(EscapeCommFunction関数)について
Windowsの場合は、直接ハードウェアを制御することは制限されていますが、シリアルポートの制御信号線の場合には専用のAPI関数としてEscapeCommFunction関数があります。出力のDTR,RTS端子の場合には、シリアルポートをオープンした後に、フラグとして表7の値を与えることで直接制御することができます。たとえば、DTR端子をオンにするときには、「5」を与えます。Win32Api.TXTの内容(EscapeCommFunction関数)は、以下のようになっています

Declare Function EscapeCommFunction Lib "kernel32" Alias "EscapeCommFunction" (ByVal nCid As Long, ByVal nFunc As Long) As Long

EscapeCommFunction関数の実行文

  戻り値 = EscapeCommFunction ( ポートのハンドル, フラグ )

表7.EscapeCommFunction関数のフラグ値
フラグの定数   値   サポートされている機能
SETRTS RTSをオンにする
CLRRTS RTSをオフにする
SETDTR DTRをオンにする
CLRDTR DTRをオフにする
SETXOFF XOFFを受信したときの処理
SETXON XONを受信したときの処理
SETBREAK 送信をブレーク状態にする
CLRBREAK 送信のブレーク状態から復帰



<項目>シリアルポートの入力制御信号の状態監視(GetCommModemStatus関数)について
シリアルポートの入力制御信号の状態監視として、DSR,CTS端子の場合には、GetCommModemStatus関数があります。パラメータから得た値に対して、表8のマスクをかけて状態を知ります。たとえば、DSR端子の場合には、&h20&と論理和をとり、0以外であればオン、0であればオフということになります。Win32Api.TXTの内容(GetCommModemStatus関数)は、以下のようになっています

Declare Function GetCommModemStatus Lib "kernel32" Alias "GetCommModemStatus" (ByVal hFile As Long, lpModemStat As Long) As Long

GetCommModemStatus関数の実行文

  戻り値 = GetCommModemStatus ( ポートのハンドル, マスク値 )

表8.GetCommModemStatus関数の
マスク値
マスクの定数   値   内容
MS_CRT_ON &H10& CTSがオン
MS_DSR_ON &H20& DSRがオン
MS_RING_ON &H40& リングがオン
MS_RLSD_ON &H80& RLSD(CD)がオン


次へは、Visual Basicプログラムの作成手順について解説していきます。


<戻る> <次ページへ>
<TOPページへ>





PC用眼鏡【管理人も使ってますがマジで疲れません】 解約手数料0円【あしたでんき】 Yahoo 楽天 NTT-X Store

無料ホームページ 無料のクレジットカード 海外格安航空券 ふるさと納税 海外旅行保険が無料! 海外ホテル